package com.atguigu.gmall.activity.consumer;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.activity.mapper.SecKillMapper;
import com.atguigu.gmall.activity.mapper.SecKillOrderMapper;
import com.atguigu.gmall.activity.service.SecKillService;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.SeckillOrder;
import com.atguigu.gmall.model.activity.UserRecode;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.io.UnsupportedEncodingException;
import java.util.Map;

/**
 * 秒杀订单监听类
 */
public class secKillOrderUpdateConsumer {

    @Autowired
    private SecKillService secKillService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SecKillOrderMapper secKillOrderMapper;

    @Autowired
    private SecKillMapper secKillMapper;

    /**
     * 监听支付状态变化的订单
     *
     * @param message
     */
    @RabbitListener(queues = "secKillQueue")
    public void updateSecKillOrder(String message) throws UnsupportedEncodingException {
        //将消息转化为map类型
        Map<String, String> map = JSONObject.parseObject(message, Map.class);
        //获取支付方式
        String payWay = map.get("payWay");
        if (payWay.equals("0")) {
            //支付方式为支付宝
            //获取支付宝支付结果
            String trade_status = map.get("trade_status");
            //支付成功修改订单状态
            if (!trade_status.isEmpty() && trade_status.equals("TRADE_SUCCESS")) {
                secKillService.paySuccess(map);
                return;
            }
            //支付失败修改订单状态
            secKillService.payFail(map);
        } else {
            //支付方式为微信
            //获取支付宝支付结果
            String return_code = map.get("return_code");
            //支付成功修改订单状态
            if (!return_code.isEmpty() && return_code.equals("SUCCESS")) {
                secKillService.paySuccess(map);
                return;
            }
            //支付失败修改订单状态
            secKillService.payFail(map);
        }
    }

    /**
     * 监听超时未支付订单
     * @param message
     */
    @RabbitListener(queues = "seckill_normal_queue")
    public void cancelSecKillOrder(String message){
        //将消息类型转换为map
        SeckillOrder seckillOrder = JSONObject.parseObject(message, SeckillOrder.class);
        //判断前置状态
        String status = seckillOrder.getStatus();
        if(!status.isEmpty() && status.equals("0")){
            //修改订单支付状态
            seckillOrder.setStatus("3");
            //将修改完后的订单跟新到redis
            redisTemplate.boundHashOps("SeckillOrder_" + seckillOrder.getUserId()).put(seckillOrder.getId(),seckillOrder);
            //将支付失败订单信息写入数据库
            secKillOrderMapper.insert(seckillOrder);
            //回滚库存信息,redis中还有库存则回滚redis，否则回滚数据库
            UserRecode userRecode = (UserRecode) redisTemplate.boundValueOps("SeckillStatus_" + seckillOrder.getUserId()).get();
            rollBack(userRecode.getGoodsId(),userRecode.getTime(),userRecode.getNum());
            //删除排队标识
            redisTemplate.delete("SeckillUserQueue_" + seckillOrder.getUserId());
            //删除排队状态
            redisTemplate.delete("SeckillStatus_" + seckillOrder.getUserId());
        }
    }

    /**
     * 回滚库存信息,redis中还有库存则回滚redis，否则回滚数据库
     * @param goodsId
     * @param time
     * @param num
     */
    private void rollBack(String goodsId, String time, Integer num) {
        //查询redis中库存信息
        SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + time).get(goodsId);
        if(seckillGoods == null){
            //商品售完，回滚数据库库存
            secKillMapper.updateSecKillGoodStock(goodsId,num);
        }
        //商品未售完，回滚redis库存
        String[] goodsQueue = getSeckillGoodsQueue(goodsId, num);
        redisTemplate.boundListOps("seckillGoodsQueue_" + goodsId).leftPushAll(goodsQueue);
        redisTemplate.boundHashOps("SeckillGoodsStockNum").increment(goodsId,num);
    }

    /**
     * 构建商品库存个数长度的数组
     * @param goodsId
     * @param stockCount
     * @return
     */
    private String[] getSeckillGoodsQueue(String goodsId, Integer stockCount) {
        //构建一个库存长度的数组
        String[] ids = new String[stockCount];
        //元素填充
        for (int i = 0; i < stockCount; i++) {
            ids[i] = goodsId;
        }
        //返回数据
        return ids;
    }
}
